---
title: 'Update data with mutations'
sidebar_title: '8. Update data with mutations'
description: Learn how to update data with the useMutation hook
---

import { MultiCodeBlock } from 'gatsby-theme-apollo-docs';
import Disclaimer from '../../shared/disclaimer.mdx';

> Time to accomplish: 10 minutes

Now that we've [added multiple queries](./queries/) to our React app, let's add a **mutation**. The process is similar, with a few important differences.

As a reminder, mutations are GraphQL operations that can modify back-end data (unlike queries). Our server's schema supports the following mutations:

```graphql
# YOU DON'T NEED TO COPY THIS.
type Mutation {
  bookTrips(launchIds: [ID]!): TripUpdateResponse!
  cancelTrip(launchId: ID!): TripUpdateResponse!
  login(email: String): String # login token
}
```

We'll start by implementing the ability to log in. Notice that this mutation accepts a single variable, `email`. 

<Disclaimer />

## Support user login

> **Note:** For simplicity, our example application doesn't implement actual user accounts with password-based authentication. Instead, a user unsecurely "logs in" by submitting their email address and receiving a corresponding session token from the server.

### Define the mutation

 To start, navigate to `src/pages/login.tsx` and replace its contents with the following:

<MultiCodeBlock>

```tsx:title=src/pages/login.tsx
import React from 'react'; // preserve-line
import { gql, useMutation } from '@apollo/client'; // preserve-line

import { LoginForm, Loading } from '../components'; // preserve-line
import * as LoginTypes from './__generated__/Login';

export const LOGIN_USER = gql`
  mutation Login($email: String!) {
    login(email: $email) {
      id
      token
    }
  }
`;
```

</MultiCodeBlock>

Our `LOGIN_USER` definition looks just like our queries from the previous section, except it replaces the word `query` with `mutation`. We receive a `User` object in the response from `login`, which includes two fields that we'll use:

* The user's `id`, which we'll use to fetch user-specific data in future queries
* A session `token`, which we'll use to "authenticate" future GraphQL operations

### Apply the `useMutation` hook

We'll use Apollo Client's `useMutation` [React Hook](https://reactjs.org/docs/hooks-intro.html) to execute our `LOGIN_USER` mutation. As with `useQuery`, the hook's result provides properties that help us populate and render our component throughout the mutation's execution.

_Unlike_ `useQuery`, `useMutation` doesn't execute its operation as soon as its component renders. Instead, the hook returns a **mutate function** that we call to execute the mutation whenever we want (such as when the user submits a form).

Add the following to the bottom of `login.tsx`:

<MultiCodeBlock>

```tsx:title=src/pages/login.tsx
export default function Login() {
  const [login, { loading, error }] = useMutation<
    LoginTypes.Login,
    LoginTypes.LoginVariables
  >(LOGIN_USER);

  if (loading) return <Loading />;
  if (error) return <p>An error occurred</p>;

  return <LoginForm login={login} />;
}
```

</MultiCodeBlock>

* The first object in `useMutation`'s result tuple (`login`) is the mutate function we call to execute the mutation. We pass this function to our `LoginForm` component.
* The second object in the tuple is similar to the result object returned by `useQuery`, including fields for the operation's `loading` and `error` states and the operation's result `data`.

Now whenever a user submits the login form, our `login` mutation is called. The user's `token` is stored in the in-memory cache, _however_ we want that token to be available across multiple visits in the same browser. Let's tackle that next.

#### Persist the user's token and ID

In our call to `useMutation`, we can include an `onCompleted` callback. This enables us to interact with the mutation's result data as soon as it's available. We'll use this callback to persist the user's `token` and `id`.

Modify the `useMutation` call in `login.tsx` to match the following:

```tsx:title=src/pages/login.tsx
const [login, { loading, error }] = useMutation<
  LoginTypes.Login,
  LoginTypes.LoginVariables
>(
  LOGIN_USER,
  {
    onCompleted({ login }) {
      if (login) {
        localStorage.setItem('token', login.token as string);
        localStorage.setItem('userId', login.id as string);
      }
    }
  }
);
```

Our `onCompleted` callback stores the user's unique ID and session token in `localStorage`, so we can load these values into the in-memory cache the next time the user visits our application. We'll add that functionality in the next chapter.

### Add `Authorization` headers to all requests

Our client should provide the user's token with each GraphQL operation it sends to our server. This enables the server to verify that the user has permission to do what they're trying to do.

In `index.tsx`, let's modify the constructor of `ApolloClient` to define a default set of `headers` that are applied to every GraphQL request: 

<MultiCodeBlock>

```tsx{4-6}:title=src/index.tsx
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
  cache,
  uri: 'http://localhost:4000/graphql',
  headers: {
    authorization: localStorage.getItem('token') || '',
  }
});
```

</MultiCodeBlock>

Our server can ignore the token when resolving operations that don't require it (such as fetching the list of launches), so it's fine for our client to include the token in every request.

### Enable the login form

We're finished defining our `login` mutation, but we don't yet display the form that enables a user to execute it. Because we're storing the user token locally, we'll use Apollo Client's local state APIs to power some of the form's logic in the next section.
